package myjava.l_reflect.reflect;


import myjava.l_reflect.pojo.Person;

/**
 * @Auther: cty
 * @Date: 2020/2/19 11:35
 * @Description: 获取类对象
 * 一、反射概念导引
 *      1 Java核心思想--面向对象
 *          万事万物皆对象，即所有的事物都具备一些特征，根据这些特征抽象成Java类，再由Java类创建具体的对象进行操作。
 *          Java类创建的具体的对象称为“类的对象”。
 *          Java类由属性、方法和构造器组成，Java类、属性、方法和构造器作为事物也有其特征。
 *      2 Java类、属性、方法和构造器特征分析
 *          （1）Java类特征
 *                  构造器 属性 方法
 *          （2）属性特征
 *                  修饰符 类型 属性名 属性值
 *          （3）方法特征
 *                  修饰符 返回值类型 方法名 形参 方法体
 *          （4）构造器特征
 *                  修饰符 形参 构造器名 方法体
 *          因此，Java类、属性、方法和构造器这四种事物都可以抽象成Java类。
 *      3 四个特殊的Java类（反射类）
 *          （1）Java类的类——class
 *                  作用：可以完整的描述一个Java类。
 *                  由class创建的对象称为“类对象”，是一种特殊的“类的对象”。
 *                  每个Java类都对应一个类对象，这个类对象可以完整的描述这个Java类。
 *                  理解：
 *                      要理解好Java类、对象、class和类对象这四个概念之间的关系。
 *          （2）属性的类——Field
 *                  作用：可以完整的描述Java类的一个属性。
 *                  Field创建的对象是属性对象，属性对象（或属性对象数组，因为一个Java类可能有多个属性）是类对象的一个属性。
 *          （3）方法的类——Method
 *                  作用：可以完整的描述Java类的一个方法。
 *                  Method创建的对象是方法对象，方法对象（或方法对象数组）是类对象的一个属性。
 *          （4）构造器的类——Constructor
 *                  作用：可以完整的描述Java类的一个构造器。
 *                  Constructor创建的对象是构造器对象，构造器对象（或构造器对象数组）是类对象的一个属性。
 *      4 传统方法操作对象
 *          （1）操作步骤
 *                  ① 导入类
 *                  ② new对象
 *                  ③ 操作对象
 *          （2）问题分析
 *                  ① 有时候程序运行时提前不知道操作的对象属于哪个类，由用户请求来决定，如何操作对象？——动态问题
 *                  ② 有时候想要更改使用的类，代码中需要修改的地方很多，如何能很方便的更换使用的类？——耦合问题
 *                  反射可以解决以上问题，可以在程序运行时动态获取类的信息和操作对象，可以降低代码的耦合性，方便更换使用的类。
 *
 * 二、反射概念解读
 *      1 什么是反射？
 *          （1）宏观来讲：
 *                  Java反射机制是在运行状态中，对于任意一个类，都能够知道这个类的所有属性和方法；对于任意一个对象，
 *                  都能够调用它的任意一个方法和属性。
 *                  这种动态获取类的信息和操作对象属性和方法的功能成为Java语言的反射机制。
 *                  称为动态，是因为编写程序时不确定要操作的是哪一个类的对象，运行时根据反射机制可以操作任何一个类的对象。
 *          （2）具体来讲：
 *                  反射将Java类、属性、方法、构造器都抽象成Java类，其中Java类的类（class）创建的对象叫类对象，属性类（Field）、
 *                  方法类（Method）和构造器类（Constructor）的对象都是类对象的属性。
 *                  反射的过程就是① 获取类对象，② 获取属性对象（方法对象或构造器对象），③ 操作属性对象（方法对象或构造器对象）的过程。
 *                  （实际上使用传统方法new对象时，JVM也是通过加载类对象来创建实例对象的，这里不做深究）
 *      2 反射有什么缺点？
 *          （1）性能差，效率低，是一种解释操作，操作属性和方法时要远慢于传统方式
 *          （2）代码复杂，不易阅读
 *          因此，实际开发中根据需求才使用反射。
 *
 * 三、获取类对象
 *      反射获取类对象的三种方式:
 * 	        Class.forName();    //根据全限定路径获取(必须会)
 * 	        对象名.getClass();  //根据对象获取
 * 	        类名.class;         //根据类名获取
 *
 * 四、操作属性
 *
 * 五、操作方法
 *
 * 六、操作构造器
 *
 *
 * 参考：
 *      [反射](https://blog.csdn.net/xylyaya/article/details/104211574)
 * @version: 1.0
 */
public class GetClassObj {
    public static void main(String[] args) {
        try {
            // 第一种方式--->根据全限定路径获取(必须会)
            Class cla01=Class.forName("myjava.l_reflect.pojo.Person");
            // 第二种方式---->调用底层使用反射封装的方法，根据类名获取
            Class cla02= Person.class;
            // 第三种方式---->调用底层使用反射封装的方法，根据对象获取
            Class cla03=new Person().getClass();

            // 注意：一个类只有一个类对象，上述三种方式获取的类对象都是同一个
            if(cla01 == cla02){
                System.out.println("第一种方式和第二种方式获取的类对象是同一个。");
            }
            if(cla02 == cla03){
                System.out.println("第二种方式和第三种方式获取的类对象是同一个。");
            }
            System.out.println("**********************************************************");

            //class类的常用方法
            System.out.println("获取类对象的包名---->"+cla01.getPackage());
            System.out.println("获取类的修饰符----->"+cla01.getModifiers());
            System.out.println("获取类的名称(全限定)----->"+cla01.getName());
            System.out.println("获取类的名称(类名)----->"+cla01.getSimpleName());
            System.out.println("获取类的父类的类对象----->"+cla01.getSuperclass());
            System.out.println("判断对象类型----->"+Person.class.isInstance(new Person()));

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}


/* res:
第一种方式和第二种方式获取的类对象是同一个。
第二种方式和第三种方式获取的类对象是同一个。
****************************************************************************
获取类对象的包名---->package com.cty.pojo
获取类的修饰符----->1
获取类的名称(全限定)----->com.cty.pojo.Person
获取类的名称(类名)----->Person
获取类的父类的类对象----->class java.lang.Object
判断对象类型----->true
*/
